package com.ebelter.scaleblesdk.ble.bluetooth.device;

import android.os.Handler;
import android.os.HandlerThread;

import com.ebelter.scaleblesdk.ble.bluetooth.BluetoothUtil;
import com.ebelter.scaleblesdk.ble.bluetooth.IWeightMessageCallBack;
import com.ebelter.scaleblesdk.ble.model.AlarmClock;
import com.ebelter.scaleblesdk.ble.model.FatResult;
import com.ebelter.scaleblesdk.model.Scale;
import com.ebelter.scaleblesdk.model.ScaleUser;
import com.ebelter.scaleblesdk.model.Weight;
import com.ebelter.scaleblesdk.util.EncryptUtilNew;
import com.ebelter.scaleblesdk.util.ULog;

import java.util.Calendar;
import java.util.HashSet;


/**
 * 体重秤返回数据处理
 *
 * @author fenghui
 */
public class WeightDataHandle extends AbstractDeviceDataHandle {

    protected Handler mHandler = null;
    private long sendDataTime = 0;
    private int sendDataTimeout = 2000;

    private long setClockTime = 0L;
    private long scaleWakedTime = 0;
    private boolean isNeedEncrypt = false;
    private final static byte HEAD_UP = (byte) 0x8d;
    private final static byte HEAD_DOWN = (byte) 0xab;

    private HashSet<String> recordSet = new HashSet<String>();

    //数据通信加密密钥
    static final byte[] SecretKey = {
            (byte) 0x16,
            (byte) 0x15,
            (byte) 0x14,
            (byte) 0x13,
            (byte) 0x12,
            (byte) 0x11
    };

    //应答ACK相关
    enum EnumAck {
        ACK_GET_SDKAUTH,            //获取sdk授权应答
        ACK_SET_CLOCK,                //设置时钟应答（当前始终消息）
        ACK_SET_SCALEUNIT,            //设置单位应答
        ACK_SET_CUSTOM,                //设置当前用户应答
        ACK_GET_ALARM,                //获取闹钟应答
        ACK_SET_ALARM,                //设置闹钟应答
        ACK_DEL_ALARM,                //下发删除闹钟应答
        ACK_GET_CURRRESULT,            //连接之后获取连接成功前测量结果的应答
        ACK_GET_OTA_UPGRADE_REQ,    //下发OTA升级请求
        ACK_SET_OTA,                //OTA升级包应答
        ACK_GET_RECOED,                //获取历史记录应答（历史记录结果）
        ACK_GET_VERSION,            //获取版本应答
        ACK_GET_LAST_MEASURE,        //获取最近一次测量结果
        ACK_BIND_USER,
        ACK_USER_AUTH
    }

    /**
     * OTA 升级类型-蓝牙
     */
    public final static int OTA_TYPE_BLE = 1;

    /**
     * OTA 升级类型-秤
     */
    public final static int OTA_TYPE_SCALE = 2;

    /**
     * OTA 升级类型-系数
     */
    public final static int OTA_TYPE_COEFFIIENT = 4;

    /**
     * OTA 升级类型-公式
     */
    public final static int OTA_TYPE_FORMULA = 8;

    RepeatSendThread repeatSendThread = null;
    EnumAck expectAck;                //预期ACK

    //称重单位
    public static enum WeightUnit {
        UNIT_KG,
        UNIT_POWND
    }

    public WeightDataHandle(IWeightMessageCallBack callback) {
        super(callback);
        this.deviceType = BluetoothUtil.DEVICETYPE_TIZHICHENG;
        this.TAG = "WeightDataHandle";
    }

    @Override
    protected void sendDataToDevice(byte[] bs) {
        sendDataTime = System.currentTimeMillis();
        //TODO 此处需要添加数据加密处理
        ULog.i(TAG, "send data to device, data is : " + bytestoString(bs));
        if (isDataEncrypt() && (bs[0]) == HEAD_DOWN) {
            byte[] dataTemp = bs.clone();
            for (int i = 3, j = 0; i < dataTemp.length; i++, j++) {
                dataTemp[i] ^= SecretKey[j % 6];
            }
            ULog.d(TAG, "send data to device, data encrypt is :" + bytestoString(dataTemp));
            if (isNeedEncrypt) {//数据为加密数据时，需要处理，AH100数据不加密，所以不需解密处理
                //保存用户认证数据为加密key
                if ((dataTemp[2] & 0xff) == 36) {
                    byte[] keyArr = new byte[7];
                    System.arraycopy(dataTemp, 3, keyArr, 0, 7);
                    ULog.d(TAG, "set auth keyArr:" + bytestoString(keyArr));
                    EncryptUtilNew.setKeyBytes(keyArr);
                }

                if (dataTemp[2] == 9) {    //下发用户信息的时候，加密处理
                    //将要加密的内容先进行加密处理
                    byte[] sendData = new byte[dataTemp.length - 3];
                    System.arraycopy(dataTemp, 3, sendData, 0, sendData.length);
                    byte[] encryData = null;
                    try {
                        //加密数据内容串
                        encryData = EncryptUtilNew.encrypt(sendData);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    if (encryData != null) {
                        //拼装数据，数据包头前三位+后面的加密16位
                        byte[] sendEncryData = new byte[encryData.length + 3];
                        System.arraycopy(dataTemp, 0, sendEncryData, 0, 3);
                        System.arraycopy(encryData, 0, sendEncryData, 3, encryData.length);
                        sendEncryData[0] = (byte) 0xdc;
                        ULog.i(TAG, "aes加密后的用户信息：" + bytestoString(sendEncryData));
                        dataTemp = sendEncryData;
                    }
                }
            }
            int cmdCode = dataTemp[2] & 0xff;
            ULog.i(TAG, "-------sendDataToDevice--------cmdCode = "  + cmdCode);
            this.msgCallBack.writeData(dataTemp);
        } else {
            this.msgCallBack.writeData(bs);
        }
    }

    //待解密第一包数据
    byte[] firstPkgData = null;

    @Override
    public void handlerData(byte[] data, String dataStr) {

        //处理蓝牙加密数据
        if ((data[0] & 0xff) == 188) {        //0xbc蓝牙aes加密数据
            if (isNeedEncrypt) {//数据为加密数据时，需要处理，AH100数据不加密，所以不需解密处理
                if ((data[2] & 0xff) == 14) {    //脂肪测量结果第1包
                    try {
                        firstPkgData = new byte[16];
                        System.arraycopy(data, 3, firstPkgData, 0, 16);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return;
                } else if ((data[2] & 0xff) == 142 && firstPkgData != null) {    //脂肪测量结果第2包
                    try {
                        //拼装并解密数据
                        byte[] secondPkgData = new byte[16];
                        System.arraycopy(data, 3, secondPkgData, 0, 16);

                        byte[] encryData1 = null;
                        byte[] encryData2 = null;
                        try {
                            encryData1 = EncryptUtilNew.decrypt(firstPkgData);
                            encryData2 = EncryptUtilNew.decrypt(secondPkgData);

                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        if (encryData1 == null || encryData2 == null) {
                            return;
                        }
                        byte[] newData = new byte[3 + encryData1.length + encryData2.length];
                        newData[0] = (byte) 0xbd;
                        newData[1] = data[1];
                        newData[2] = (byte) 0x0e;

                        System.arraycopy(encryData1, 0, newData, 3, encryData1.length);
                        System.arraycopy(encryData2, 0, newData, 3 + encryData1.length, encryData2.length);

                        ULog.i(TAG, "测量结果解密后数据内容：" + bytestoString(newData));

                        data = newData;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        firstPkgData = null;
                    }
                } else if ((data[2] & 0xff) == 16) {    //历史记录结果第1包
                    try {
                        firstPkgData = new byte[16];
                        System.arraycopy(data, 3, firstPkgData, 0, 16);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return;
                } else if ((data[2] & 0xff) == 144 && firstPkgData != null) {    //历史记录结果第2包
                    try {
                        //拼装并解密数据
                        byte[] secondPkgData = new byte[16];
                        System.arraycopy(data, 3, secondPkgData, 0, 16);

                        byte[] encryData1 = null;
                        byte[] encryData2 = null;
                        try {
                            encryData1 = EncryptUtilNew.decrypt(firstPkgData);
                            encryData2 = EncryptUtilNew.decrypt(secondPkgData);

                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        if (encryData1 == null || encryData2 == null) {
                            return;
                        }
                        byte[] newData = new byte[3 + encryData1.length + encryData2.length];
                        newData[0] = (byte) 0xbd;
                        newData[1] = data[1];
                        newData[2] = (byte) 0x10;

                        System.arraycopy(encryData1, 0, newData, 3, encryData1.length);
                        System.arraycopy(encryData2, 0, newData, 3 + encryData1.length, encryData2.length);

                        ULog.i(TAG, "历史数据解密后数据内容：" + bytestoString(newData));

                        data = newData;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        firstPkgData = null;
                    }
                }
            }
        }
        /*if (this.isDataEncrypt() && (data[0]) == HEAD_UP) {
            byte[] dataTemp = data.clone();
            byte[] macAddr = getDeviceAddressBytes();
            for (int i = 3, j = 0; i < dataTemp.length; i++, j++) {
                data[i] ^= macAddr[j % 6];
            }
            ULog.i(TAG, "data deEncrypt is :" + bytestoString(data));
        }

        //过滤掉连续接收到的消息
        if (super.isTheSameData(dataStr)) {
            return;
        }*/
        //校验数据长度= 数据长度(data[1])+命令(1)+包头(1)+xor(1)
        if (data.length >= 2
                && (data[0]) == HEAD_UP
                && data.length == (data[1] & 0xff) + 3) {

            int year1, year2, year, month, date, hour, minute, second, weekOfYear, no, userId,
                    weight1, weight2, weight, fat1, fat2, fat, resistance1, resistance2, resistance;
            FatResult fatResultBean;
            Weight weightBean;

            int cmdCode = data[2] & 0xff;
            ULog.i(TAG, "-------handlerData--------cmdCode = "  + cmdCode);
            switch (cmdCode) {
                case 0x90:        //秤已唤醒
                    ULog.i(TAG, "receive scale wakeup.data[2] = " + data[2]);

//                    if (System.currentTimeMillis() - scaleWakedTime > 2000) {
                        ((IWeightMessageCallBack) msgCallBack).onScaleWake();
//                    }
                    scaleWakedTime = System.currentTimeMillis();

                    recordSet.clear();
                    break;
                case 0x91:        //秤已休眠
                    ULog.i(TAG, "receive scale sleeped.");
                    ((IWeightMessageCallBack) msgCallBack).onScaleSleep();
                    recordSet.clear();
                    break;
                case 0x92:        //称重单位
                    ULog.i(TAG, "receive scale change unit.");
                    expectAck = EnumAck.ACK_SET_SCALEUNIT;

                    WeightUnit scaleUnit = data[3] == 1 ? WeightUnit.UNIT_KG : WeightUnit.UNIT_POWND;
                    ((IWeightMessageCallBack) msgCallBack).onUnitSet(scaleUnit);
                    break;
                case 0x9c:    //接收到版本信息
                    ULog.i(TAG, "receive scale version info.");
                    expectAck = EnumAck.ACK_GET_VERSION;

                    //ble固件
                    int ble0 = data[3] & 0xff;
                    int ble1 = data[4] & 0xff;
                    //秤固件
                    int scale0 = data[5] & 0xff;
                    int scale1 = data[6] & 0xff;
                    //系数固件
                    int coefficient0 = data[7] & 0xff;
                    int coefficient1 = data[8] & 0xff;
                    //算法固件
                    int arithmetic0 = data[9] & 0xff;
                    int arithmetic1 = data[10] & 0xff;

                    int bleVer = (ble1 << 8) | ble0;
                    int scaleVer = (scale1 << 8) | scale0;
                    int coefficientVer = (coefficient1 << 8) | coefficient0;
                    int arithmeticVer = (arithmetic1 << 8) | arithmetic0;
                    ULog.i(TAG, "receive scale version info." +
                            "bleVer:" + bleVer +
                            "scaleVer:" + scaleVer +
                            "coefficientVer:" + coefficientVer +
                            "arithmeticVer:" + arithmeticVer);
                    ((IWeightMessageCallBack) msgCallBack).onGotScaleVersion(bleVer, scaleVer, coefficientVer, arithmeticVer);

                    Scale.getInstance().setOtaVersion(scaleVer);
                    break;
                case 0x93:        //接收到第n组闹钟
                    ULog.i(TAG, "receive scale clock data.");
                    expectAck = EnumAck.ACK_GET_ALARM;

                    no = data[3] & 0xff;
                    hour = data[8] & 0xff;
                    minute = data[9] & 0xff;
                    int clockRepeat = data[11] & 0xff;
                    int onOrOff = clockRepeat & 128;
                    int loonState = data[12] & 0xff;
//                    int[] clockRepeatArr = {
//                            (clockRepeat & 64) > 0 ? 1 : 0,
//                            (clockRepeat & 32) > 0 ? 1 : 0,
//                            (clockRepeat & 16) > 0 ? 1 : 0,
//                            (clockRepeat & 8) > 0 ? 1 : 0,
//                            (clockRepeat & 4) > 0 ? 1 : 0,
//                            (clockRepeat & 2) > 0 ? 1 : 0,
//                            (clockRepeat & 1) > 0 ? 1 : 0,
//                    };

                    int[] clockRepeatArr = {
                            (clockRepeat & 1) > 0 ? 1 : 0,
                            (clockRepeat & 2) > 0 ? 1 : 0,
                            (clockRepeat & 4) > 0 ? 1 : 0,
                            (clockRepeat & 8) > 0 ? 1 : 0,
                            (clockRepeat & 16) > 0 ? 1 : 0,
                            (clockRepeat & 32) > 0 ? 1 : 0,
                            (clockRepeat & 64) > 0 ? 1 : 0
                    };

                    ULog.i(TAG, "receive clock data" +
                            ",no: " + no +
                            ",hour: " + hour +
                            ",minute: " + minute +
                            ",clockRepeat: " + Integer.toBinaryString(clockRepeat));
                    AlarmClock bean = new AlarmClock();
                    bean.setNo(no);
                    bean.setHour(hour);
                    bean.setMinute(minute);
                    bean.setOnOff(onOrOff > 0);
                    bean.setWeekRepeat(clockRepeatArr);
                    bean.setLoonState(loonState == 0);
                    ((IWeightMessageCallBack) msgCallBack).onGotAlarm(bean);
                    break;
                case 0x98:        //接收到当前时钟
                    ULog.i(TAG, "receive scale clock.");
                    expectAck = EnumAck.ACK_SET_CLOCK;

                    year1 = data[3] & 0xff;
                    year2 = data[4] & 0xff;
                    year = (year2 << 8) | year1;

                    month = data[5] & 0xff;
                    date = data[6] & 0xff;

                    hour = data[7] & 0xff;
                    minute = data[8] & 0xff;
                    second = data[9] & 0xff;
                    weekOfYear = data[10] & 0xff;

                    ULog.i(TAG, "got scale curr clock info." +
                            "year:" + year +
                            "month:" + month +
                            "date:" + date +
                            "hour:" + hour +
                            "minute:" + minute +
                            "second:" + second +
                            "weekOfYear:" + weekOfYear);

                    Calendar cal = Calendar.getInstance();
                    cal.set(Calendar.YEAR, year);
                    cal.set(Calendar.MONTH, month - 1);
                    cal.set(Calendar.DATE, date);
                    cal.set(Calendar.HOUR_OF_DAY, hour);
                    cal.set(Calendar.MINUTE, minute);
                    cal.set(Calendar.SECOND, second);

                    long scaleDateLong = cal.getTimeInMillis();

                    //收到秤时钟小于下发的时钟1s以内为正确时钟，其它作为错误时钟，重新下发
                    ULog.i(TAG, "scaleDateLong:" + scaleDateLong + ",feng:" + setClockTime);
                    if (Math.abs(scaleDateLong - setClockTime) < 2000) {
                        ((IWeightMessageCallBack) msgCallBack).onGotScaleClock(year, month, date, hour, minute, second, weekOfYear);

                        //获取固件版本号
                        sendGetVersion();
                    } else {
                        ULog.e(TAG, "receive error clock data, do resend set clock cmd.");
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                sendSyncSystemClock();
                            }
                        }, 500);
                    }
                    break;
                case 0x9e:    //接收到体脂肪测量结果
                    ULog.i(TAG, "receive fat result.");
                    sendFatResultAck();

                    userId = data[3] & 0xff;
                    weight1 = data[4] & 0xff;
                    weight2 = data[5] & 0xff;
                    weight = (weight2 << 8) | weight1;
                    fat1 = data[6] & 0xff;
                    fat2 = data[7] & 0xff;
                    fat = (fat2 << 8) | fat1;

                    //时间
                    year1 = data[8] & 0xff;
                    year2 = data[9] & 0xff;
                    year = (year2 << 8) | year1;
                    month = data[10] & 0xff;
                    date = data[11] & 0xff;
                    hour = data[12] & 0xff;
                    minute = data[13] & 0xff;
                    second = data[14] & 0xff;
                    weekOfYear = data[15] & 0xff;

                    //过滤重复的测量时间结果
                    String testTime = year + "-" + month + "-" + date + "-"
                            + hour + "-" + minute + "-" + second;
                    if (recordSet.contains(testTime)) {
                        ULog.e(TAG, "receive same test time." + testTime);
                        return;
                    }
                    recordSet.add(testTime);

                    //电阻
                    resistance1 = data[16] & 0xff;
                    resistance2 = data[17] & 0xff;
                    resistance = (resistance2 << 8) | resistance1;

                    fatResultBean = new FatResult();
                    fatResultBean.setYear(year);
                    fatResultBean.setMonth(month);
                    fatResultBean.setDay(date);
                    fatResultBean.setHour(hour);
                    fatResultBean.setMinute(minute);
                    fatResultBean.setSecond(second);
                    fatResultBean.setWeekOfYear(weekOfYear);
                    fatResultBean.setResistance(resistance);
                    fatResultBean.setUserId(userId);
                    fatResultBean.setWeight(Float.valueOf(weight) / 10);
                    fatResultBean.setFat(Float.valueOf(fat) / 10);

                    boolean isUnitKg;
                    int unitByte= (data[18] & 0xff);
                    if (0x01==unitByte){
                        isUnitKg=false;
                    }else {
                        isUnitKg=true;
                    }

                    fatResultBean.setUnitIsKG(isUnitKg);

                    ULog.i(TAG, fatResultBean.toString());

                    ((IWeightMessageCallBack) msgCallBack).onFatMeasureResult(fatResultBean);
                    break;
                case 0x9f:    //接收到体重测量信息
                    ULog.i(TAG, "receive weight measureing data.");
                    userId = data[3] & 0xff;
                    weight1 = data[4] & 0xff;
                    weight2 = data[5] & 0xff;
                    weight = (weight2 << 8) | weight1;

                    //时间
                    year1 = data[6] & 0xff;
                    year2 = data[7] & 0xff;
                    year = (year2 << 8) | year1;
                    month = data[8] & 0xff;
                    date = data[9] & 0xff;
                    hour = data[10] & 0xff;
                    minute = data[11] & 0xff;
                    second = data[12] & 0xff;
                    weekOfYear = data[13] & 0xff;

                    weightBean = new Weight();
                    weightBean.setUserId(userId);
                    weightBean.setYear(year);
                    weightBean.setMonth(month);
                    weightBean.setDate(date);
                    weightBean.setHour(hour);
                    weightBean.setMinute(minute);
                    weightBean.setSecond(second);
                    weightBean.setWeekOfYear(weekOfYear);
                    weightBean.setWeight(Float.valueOf(weight) / 10);
                    ULog.i(TAG, weightBean.toString());
                    ((IWeightMessageCallBack) msgCallBack).onWeightMeasureResult(weightBean);
                    break;
                case 0xa0:    //接收到历史测量数据
                    ULog.i(TAG, "receive weight record data.");
                    expectAck = EnumAck.ACK_GET_RECOED;

                    userId = data[3] & 0xff;
                    weight1 = data[4] & 0xff;
                    weight2 = data[5] & 0xff;
                    weight = (weight2 << 8) | weight1;
                    fat1 = data[6] & 0xff;
                    fat2 = data[7] & 0xff;
                    fat = (fat2 << 8) | fat1;

                    //时间
                    year1 = data[8] & 0xff;
                    year2 = data[9] & 0xff;
                    year = (year2 << 8) | year1;
                    month = data[10] & 0xff;
                    date = data[11] & 0xff;
                    hour = data[12] & 0xff;
                    minute = data[13] & 0xff;
                    second = data[14] & 0xff;
                    weekOfYear = data[15] & 0xff;

                    //电阻
                    resistance1 = data[16] & 0xff;
                    resistance2 = data[17] & 0xff;
                    resistance = (resistance2 << 8) | resistance1;

                    //是否疑似数据
                    int suspectedData = data[18];


                    fatResultBean = new FatResult();
                    fatResultBean.setYear(year);
                    fatResultBean.setMonth(month);
                    fatResultBean.setDay(date);
                    fatResultBean.setHour(hour);
                    fatResultBean.setMinute(minute);
                    fatResultBean.setSecond(second);
                    fatResultBean.setWeekOfYear(weekOfYear);
                    fatResultBean.setResistance(resistance);
                    fatResultBean.setUserId(userId);
                    fatResultBean.setWeight(Float.valueOf(weight) / 10);
                    fatResultBean.setFat(Float.valueOf(fat) / 10);

                    /**
                     * 是否疑似数据
                     * 2017-02-15 17:41添加
                     */
                    fatResultBean.setSuspectedData((suspectedData & 0xff) == 170);

                    ULog.i(TAG, "receive history data : " + fatResultBean.toString());

                    ((IWeightMessageCallBack) msgCallBack).onReceiveHistoryRecord(fatResultBean);

                    break;
                case 0xa1:    //接收到升级包应答
                    expectAck = EnumAck.ACK_SET_OTA;

                    int pkg1 = data[3] & 0xff;
                    int pkg2 = data[4] & 0xff;
                    int pkg = (pkg2 << 8) | pkg1;
                    ULog.i(TAG, "redevice packageupgradeResponse is:" + pkg);
                    if ((data[5] & 0xff) <= 1) {
                        ((IWeightMessageCallBack) msgCallBack).onUpgradeResponse(pkg, (data[5] & 0xff) == 0);
                    } else {
                        ((IWeightMessageCallBack) msgCallBack).onUpgradeResponse(pkg, true);
                    }
                    break;
                case 0xa2:    //升级结果
                    expectAck = EnumAck.ACK_SET_OTA;
                    int result = data[3] & 0xff;
                    int type = data[4] & 0xff;
                    ULog.i(TAG, "package upgrade result:" + result);
                    ((IWeightMessageCallBack) msgCallBack).onUpgradeResult(result, type);
                    break;
                case 0xa3:    //体重数据
                    int status = data[3] & 0xff;
                    boolean overLoad = (status & 64) > 0;
                    if (overLoad) {
                        ULog.e(TAG, "weight over load.");
                        ((IWeightMessageCallBack) msgCallBack).onWeightOverLoad();
                    } else {
                        boolean isMeasuring = (status & 128) == 0;
                        WeightUnit unit = (status & 1) == 0 ? WeightUnit.UNIT_KG : WeightUnit.UNIT_POWND;

                        weight1 = data[4] & 0xff;
                        weight2 = data[5] & 0xff;
                        weight = (weight2 << 8) | weight1;

                        ULog.i(TAG, "weight data is :" + weight +
                                ",isMeasuring is :" + isMeasuring +
                                ",unit is : " + ((status & 1) == 0 ? "kg" : "lb"));
                    }
                    break;
                case 0xa4:    //低电提示
                    ULog.i(TAG, "receive device low power message.");
                    ((IWeightMessageCallBack) msgCallBack).onLowPower();
                    break;
                case 0xa5:    //测脂出错
                    ULog.i(TAG, "receive fat measure error message.");
                    ((IWeightMessageCallBack) msgCallBack).onFatMeasureError(data[3] & 0xff);
                    break;
                case 0xa6:    //接收到修改闹钟ACK
                    ULog.i(TAG, "receive set clock ack.");
                    expectAck = EnumAck.ACK_SET_ALARM;

                    ((IWeightMessageCallBack) msgCallBack).onSetClockAck();
                    break;
                case 0xa7:    //接收到OTA升级就绪消息
                    ULog.i(TAG, "receive OTA upgrade ready.");
                    expectAck = EnumAck.ACK_GET_OTA_UPGRADE_REQ;
                    ((IWeightMessageCallBack) msgCallBack).onOtaUpgradeReady(data[3] == 0);
                    break;
                case 0xa8:    //接收到用户列表标记值响应
                    int mark = data[3] & 0xff;
                    StringBuilder macSb = new StringBuilder();
                    macSb.append(Integer.toHexString(data[4] & 0xff).length() == 1 ? ("0" + Integer.toHexString(data[4] & 0xff)) : Integer.toHexString(data[4] & 0xff));
                    macSb.append(":");
                    macSb.append(Integer.toHexString(data[5] & 0xff).length() == 1 ? ("0" + Integer.toHexString(data[5] & 0xff)) : Integer.toHexString(data[5] & 0xff));
                    macSb.append(":");
                    macSb.append(Integer.toHexString(data[6] & 0xff).length() == 1 ? ("0" + Integer.toHexString(data[6] & 0xff)) : Integer.toHexString(data[6] & 0xff));
                    macSb.append(":");
                    macSb.append(Integer.toHexString(data[7] & 0xff).length() == 1 ? ("0" + Integer.toHexString(data[7] & 0xff)) : Integer.toHexString(data[7] & 0xff));
                    macSb.append(":");
                    macSb.append(Integer.toHexString(data[8] & 0xff).length() == 1 ? ("0" + Integer.toHexString(data[8] & 0xff)) : Integer.toHexString(data[8] & 0xff));
                    macSb.append(":");
                    macSb.append(Integer.toHexString(data[9] & 0xff).length() == 1 ? ("0" + Integer.toHexString(data[9] & 0xff)) : Integer.toHexString(data[9] & 0xff));

                    ULog.i(TAG, "receive user mark response.mark:" + mark +
                            ",mac:" + macSb.toString());
                    break;
                case 0xa9:    //秤历史记录上传完毕消息
                    ULog.i(TAG, "scale history uploaded done.");
                    expectAck = EnumAck.ACK_GET_RECOED;

                    ((IWeightMessageCallBack) msgCallBack).onHistoryUploadDone();
                    break;
                case 0xb0:    //秤响应app的列表更新指令
                    ULog.i(TAG, "scale response update list.");
                    expectAck = EnumAck.ACK_SET_CUSTOM;

                    ((IWeightMessageCallBack) msgCallBack).onListUpdate();

                    //用户列表更新成功后，发送同步时钟到秤端
                    sendSyncSystemClock();
                    break;
                case 0xb1:    //秤响应无连接前测量结果响应
                    ULog.i(TAG, "scale response no before connect data.");
                    expectAck = EnumAck.ACK_GET_LAST_MEASURE;
                    ((IWeightMessageCallBack) msgCallBack).onGotLastRecordEmpty();
                    break;
                case 0xb6:                //上传秤是否与手机绑定过
                    if (data[3] == 1) {
                        ((IWeightMessageCallBack) msgCallBack).onAuthSuccess();
                    } else {
                        ((IWeightMessageCallBack) msgCallBack).onAuthFailed();
                    }
                    break;
                case 0xb7:                //绑定确认指令
                    ((IWeightMessageCallBack) msgCallBack).onBindSuccess();
                    break;
                case 0xb8:                //OTA sha256校验码下发响应
                    if (data[3] == 1) {
                        ((IWeightMessageCallBack) msgCallBack).onReceiveSha256PkgOne();
                    } else {
                        ((IWeightMessageCallBack) msgCallBack).onReceiveSha256PkgTwo();
                    }
                    break;
                default:
                    break;
            }
        } else if ((data[0] & 0xff) == 5 && (data[1] & 0xff) == 250) {
            //receive sdk auth code
            ((IWeightMessageCallBack) msgCallBack).onSDKAuthResult(data);
        } else {
            ULog.e(TAG, "receive error data package:" + data);
        }
    }


    /**
     * 下发设置单位命令
     *
     * @param weightUnit
     */
    public void sendSetUnit(WeightUnit weightUnit) {
        ULog.i(TAG, "send set scale device unit cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x02,
                (byte) 0x92,
                0x01
        };
        if (weightUnit == WeightUnit.UNIT_KG) {
            bytes[3] = 0x01;
        } else {
            bytes[3] = 0x02;
        }

        safeguardSendData(bytes, 200, EnumAck.ACK_SET_SCALEUNIT);
    }

    /**
     * 下发设置闹钟
     *
     * @param clock
     */
    public void sendSetAlarmClock(AlarmClock clock) {
        ULog.i(TAG, "send set alarm clock cmd.");
        byte[] bytes = clock.buildCmdBytes();

        safeguardSendData(bytes, 1000, EnumAck.ACK_SET_ALARM);
    }

    /**
     * 下发删除闹钟
     *
     * @param no 闹钟编号，0-4
     */
    public void sendDeleteAlarmClock(int no) {
        ULog.i(TAG, "send delete alarm clock by no cmd.");
//		byte[] bytes = {
//			(byte)0xdb,
//			0x02,
//			0x04,
//			(byte) no
//		};

        AlarmClock clockBean = new AlarmClock();
        clockBean.setHour(255);
        clockBean.setMinute(255);
        clockBean.setSecond(255);
        clockBean.setNo(no);
        clockBean.setWeekRepeat(new int[]{0, 0, 0, 0, 0, 0, 0});

        safeguardSendData(clockBean.buildCmdBytes(), 1000, EnumAck.ACK_SET_ALARM);
    }

    /**
     * 下发删除全部闹钟
     */
    public void sendDeleteAllAlarmClock() {
        ULog.i(TAG, "send delete all alarm clock cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0x95
        };

        safeguardSendData(bytes, 500, EnumAck.ACK_DEL_ALARM);
    }

    /**
     * 下发获取第n组闹钟
     *
     * @param no 闹钟组编号 0-4
     */
    public void sendGetAlarmClockByNo(int no) {
        ULog.i(TAG, "send get alarm clock by no cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x02,
                (byte) 0x96,
                (byte) no
        };

        safeguardSendData(bytes, 200, EnumAck.ACK_GET_ALARM);
    }

    /**
     * 下发同步系统时间命令
     */
    public void sendSyncSystemClock() {
        ULog.i(TAG, "send sync system time cmd.");
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        int date = cal.get(Calendar.DATE);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        int minute = cal.get(Calendar.MINUTE);
        int second = cal.get(Calendar.SECOND);

        setClockTime = cal.getTimeInMillis();

        //TODO 需要确认
        //周一至周日，1至7
        int week = cal.get(Calendar.DAY_OF_WEEK);
        week = (week == 1) ? 7 : (week - 1);

        int yearLowHex = year & 0xff;
        int yearHeightHex = (year >> 8) & 0xff;
        byte[] bytes = {
                (byte) 0xab,
                0x09,
                (byte) 0x98,
                (byte) yearLowHex,
                (byte) yearHeightHex,
                (byte) month,
                (byte) date,
                (byte) hour,
                (byte) minute,
                (byte) second,
                (byte) week

        };

        safeguardSendData(bytes, 500, EnumAck.ACK_SET_CLOCK);
    }

    /**
     * 下发同步系统时间命令
     */
    public void sendSyncSystemClock2(int year, int month, int date, int hour, int minute,
                                     int second) {
        ULog.i(TAG, "send sync system time cmd2.");
        Calendar cal = Calendar.getInstance();
//		int year = cal.get(Calendar.YEAR);
//		int month = cal.get(Calendar.MONTH) + 1;
//		int date = cal.get(Calendar.DATE);
//		int hour = cal.get(Calendar.HOUR);
//		int minute = cal.get(Calendar.MINUTE);
//		int second = cal.get(Calendar.SECOND);
        //TODO 需要确认
        int week = cal.get(Calendar.WEEK_OF_YEAR);


        int yearLowHex = year & 0xff;
        int yearHeightHex = (year >> 8) & 0xff;
        byte[] bytes = {
                (byte) 0xab,
                0x09,
                (byte) 0x98,
                (byte) yearLowHex,
                (byte) yearHeightHex,
                (byte) month,
                (byte) date,
                (byte) hour,
                (byte) minute,
                (byte) second,
                (byte) week

        };

        safeguardSendData(bytes, 500, EnumAck.ACK_SET_CLOCK);
    }

    /**
     * 下发人体信息
     *
     * @param user
     */
    public void sendUserInfo(ScaleUser user) {
        ULog.i(TAG, "send user body info cmd." + user.getBtId());
        safeguardSendData(user.buildScaleUserData(), 1000, EnumAck.ACK_SET_CUSTOM);
    }

    /**
     * 下发选择用户
     *
     * @param userId
     */
    public void sendSelectUser(int userId) {
        ULog.i(TAG, "send select user cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x02,
                (byte) 0x9a,
                (byte) userId
        };
        this.sendDataToDevice(bytes);
    }

//	/**
//	 * 下发获取秤历史记录(2017-03-04新增)
//	 */
//	public void sendGetRecord(String mac) {
//		ULog.i(TAG, "send get record cmd, mac is : " + mac);
//		String[] macArr = mac.split(":");
//
//		byte[] bytes = {
//			(byte) 0xdb,
//			0x07,
//			(byte) 0x0b,
//			(byte) Integer.parseInt(macArr[0], 16),
//			(byte) Integer.parseInt(macArr[1], 16),
//			(byte) Integer.parseInt(macArr[2], 16),
//			(byte) Integer.parseInt(macArr[3], 16),
//			(byte) Integer.parseInt(macArr[4], 16),
//			(byte) Integer.parseInt(macArr[5], 16),
//			0x00
//		};
//
//		safeguardSendData(bytes, 1000, EnumAck.ACK_GET_RECOED);
//	}


    public void sendGetRecord(String uid) {
        ULog.i(TAG, "send get record cmd, uid is : " + uid);
        String[] uidArr = uid.split(":");

        if (uidArr.length != 7) {
            uidArr = new String[]{"0", "0", "0", "0", "0", "0", "0"};
        }

        byte[] bytes = {
                (byte) 0xab,
                0x07,
                (byte) 0x9b,
                (byte) Integer.parseInt(uidArr[0], 16),
                (byte) Integer.parseInt(uidArr[1], 16),
                (byte) Integer.parseInt(uidArr[2], 16),
                (byte) Integer.parseInt(uidArr[3], 16),
                (byte) Integer.parseInt(uidArr[4], 16),
                (byte) Integer.parseInt(uidArr[5], 16),
                (byte) Integer.parseInt(uidArr[6], 16),
                0x00
        };

        safeguardSendData(bytes, 1000, EnumAck.ACK_GET_RECOED);
    }

    /**
     * 下发获取秤历史记录（兼容老版本获取历史记录）
     */
    public void sendGetRecord() {
        ULog.i(TAG, "send get record cmd.");
        byte[] bytes = {
                (byte) 0xdb,
                0x02,
                (byte) 0x0b,
                0x00
        };

        safeguardSendData(bytes, 1000, EnumAck.ACK_GET_RECOED);
    }

    /**
     * 下发获取秤历史记录 ACK
     */
    public void sendGetRecordAck() {
        ULog.i(TAG, "send get record ack cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x02,
                (byte) 0x9b,
                0x01
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 下发查询版本
     */
    public void sendGetVersion() {
        ULog.i(TAG, "send get version cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0x9c
        };
        safeguardSendData(bytes, 500, EnumAck.ACK_GET_VERSION);
    }

    //下发OTA请求升级
    public void sendOTAUpdateRequest(int type, int pkgLen, int cs) {
        ULog.i(TAG, "send ota updarge request cmd.");
        int lenLowHex = pkgLen & 0xff;
        int lenHeightHex = (pkgLen >> 8) & 0xff;

        byte[] bytes = {
                (byte) 0xab,
                0x05,
                (byte) 0x9d,
                (byte) type,
                (byte) lenLowHex,
                (byte) lenHeightHex,
                (byte) cs
        };

        safeguardSendData(bytes, 1000, EnumAck.ACK_GET_OTA_UPGRADE_REQ);
    }

    //下发OTA请求升级(2017-05-05新增，crc8校验）

    /**
     *
     * @param type   01:蓝牙固件,02：秤固件
     * @param pkgLen 整包长度
     * @param cs  CRC8校验值
     */
    public void sendOTAUpdateRequestCRC(int type, int pkgLen, int cs) {
        ULog.i(TAG, "send ota updarge request cmd. cs:" + Integer.toHexString(cs));
        int lenLowHex = pkgLen & 0xff;
        int lenHeightHex = (pkgLen >> 8) & 0xff;

        byte[] bytes = {
                (byte) 0xab,
                0x06,
                (byte) 0x9d,
                (byte) type,
                (byte) lenLowHex,
                (byte) lenHeightHex,
                (byte) cs,
                0
        };

        safeguardSendData(bytes, 1000, EnumAck.ACK_GET_OTA_UPGRADE_REQ);
    }

    /**
     * 下发ota升级结束指令
     */
    public void sendOtaFinishCmd() {
        ULog.i(TAG, "send ota finish cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x05,
                (byte) 0x9d,
                (byte) 0xaa,
                0x00,
                0x00,
                0x00
        };
        sendDataToDevice(bytes);
    }

    /**
     * 下发获取设备当前时钟
     */
    public void sendGetScaleClock() {
        ULog.i(TAG, "send get scale clock cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0x9e
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 下发获取用户列表mark
     */
    public void sendGetUserListMark() {
        ULog.i(TAG, "send get user list mark cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0x9f
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 标记列表更新的状态
     *
     * @param mac  mac地址
     * @param mark 标记
     */
    public void sendUpdateSign(String mac, int mark) {
        ULog.i(TAG, "send update sign user mark cmd.");
        String[] macArr = mac.split(":");
        if (macArr.length != 6) {
            ULog.e(TAG, "mac is error");
            macArr = new String[]{"0", "0", "0", "0", "0", "0"};
        }
        byte[] bytes = {
                (byte) 0xab,
                0x08,
                (byte) 0xa0,
                (byte) mark,
                (byte) Integer.parseInt(macArr[0], 16),
                (byte) Integer.parseInt(macArr[1], 16),
                (byte) Integer.parseInt(macArr[2], 16),
                (byte) Integer.parseInt(macArr[3], 16),
                (byte) Integer.parseInt(macArr[4], 16),
                (byte) Integer.parseInt(macArr[5], 16)
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 下发获取SDK授权
     *
     * @param bytes
     */
    public void sendGetSDKAuth(byte[] bytes) {
        ULog.i(TAG, "下发获取sdk授权信息");
        safeguardSendData(bytes, 1000, EnumAck.ACK_GET_SDKAUTH);
    }

    /**
     * 下发OTA分包数据
     * 2017-02-11
     *
     * @param bs    数据包内容
     * @param pkgNo 第N个包
     */
    public void sendOTAPackage(byte[] bs, int pkgNo) {
        ULog.i(TAG, "send ota package data cmd.");
        int bsLen = bs.length;
        ULog.i(TAG, "pkg data len:" + bsLen + ",data is : " + bytestoString(bs));
        //包号，总包数大，一个字节存不完，需分高8位，低8位
        int noLowHex = pkgNo & 0xff;
        int noHeightHex = (pkgNo >> 8) & 0xff;
        //bytes为传输的数据包，第0个字节为包头，第1个为指令，第2--3个为包号，
        byte[] bytes = new byte[20];
        bytes[0] = (byte) 0xad;
        bytes[1] = (byte) 0x12;
        bytes[2] = (byte) noLowHex;
        bytes[3] = (byte) noHeightHex;

        //第4--19个为数据，数据长度不够16，则用0xff填充
        for (int i = 4, j = 0; i < 20; i++, j++) {
            if (j >= bsLen) {
                bytes[i] = (byte) 0xff;
            } else {
                bytes[i] = bs[j];
            }
        }


        //后18位做xor亦或校验，存入bytes[1]
        byte csXor = 0;
        for (int i = 2; i < bytes.length; i++) {
            csXor ^= bytes[i];
        }
        bytes[1] = csXor;
        //Fat Body协议修改
        bytes[2] = (byte) (((pkgNo & 0xff) + 0x90) & 0xff);
//		bytes[21] = 0x11;
//		bytes[22] = 0x00;

        safeguardSendData(bytes, 1000, EnumAck.ACK_SET_OTA);
    }

    /**
     * 下发删除所有用户指令
     */
    public void sendDelAllUser() {
        ULog.i(TAG, "send delete all user list cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x02,
                (byte) 0xa1,
                0x00
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 调试用
     * 下发设置蓝牙息屏后蓝牙广播时间
     *
     * @param seconds
     */
    public void sendSetBleBroadcastTime(int seconds) {
        ULog.i(TAG, "send set ble broadcast time cmd.");
        int halfSeconds = seconds * 2;
        int secLowHex = halfSeconds & 0xff;
        int secHeightHex = (halfSeconds >> 8) & 0xff;
        byte[] bytes = {
                (byte) 0xdb,
                0x03,
                (byte) 0x12,
                (byte) secLowHex,
                (byte) secHeightHex
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 测量完成后，手机连上秤的场景，此场景，手机端无法判断，未使用
     * <p>
     * 下发获取最近一次测量数据（秤测量完成后才连接上设备的时候，app主动查询秤当前的结果，并保存到app）
     */
    public void sendGetLastRecord() {
        ULog.i(TAG, "send get last record data cmd.");
        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0xa4
        };
        safeguardSendData(bytes, 500, EnumAck.ACK_GET_LAST_MEASURE);
    }

    /**
     * 手机端接收完成后，发给秤的响应，标识已完成接收，防止丢包
     * <p>
     * 下发接收到脂肪测量结果ACK
     */
    public void sendFatResultAck() {
        ULog.i(TAG, "send fat result ack response.");
        byte[] bytes = {
                (byte) 0xab,
                0x02,
                (byte) 0xa3,
                0x00
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * 下发断开设备蓝牙
     */
    @Override
    public void sendDisconnectBt() {
        ULog.i(TAG, "send disconnect bluetooth device.");
        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0xa6
        };
        this.sendDataToDevice(bytes);
    }

    /**
     * /**
     * 下发心跳指令
     */
    public void sendHeartBeatCmd() {
        ULog.d(TAG, "send bt heartbeat cmd.");

        byte[] bytes = {
                (byte) 0xab,
                0x01,
                (byte) 0xb0
        };

        this.sendDataToDevice(bytes);
    }

    /**
     * 下发认证指令
     */
    public void sendAuthCmd(byte[] deviceId) {
        //TODO deviceId的生成
        //byte[] deviceId = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
        byte[] bytes = new byte[10];
        bytes[0] = (byte) 0xdb;
        bytes[1] = (byte) 0x08;
        bytes[2] = (byte) 0x24;

        bytes[3] = deviceId[0];
        bytes[4] = deviceId[1];
        bytes[5] = deviceId[2];
        bytes[6] = deviceId[3];
        bytes[7] = deviceId[4];
        bytes[8] = deviceId[5];
        bytes[9] = deviceId[6];

        //this.sendDataToDevice(bytes);
        this.safeguardSendData(bytes, 500, EnumAck.ACK_USER_AUTH);
    }

    /**
     * 下发绑定用户指令
     */
    public void sendBindUserCmd(byte[] deviceId) {
        //TODO deviceId的生成
        //byte[] deviceId = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
        byte[] bytes = new byte[10];
        bytes[0] = (byte) 0xdb;
        bytes[1] = (byte) 0x08;
        bytes[2] = (byte) 0x25;

        bytes[3] = deviceId[0];
        bytes[4] = deviceId[1];
        bytes[5] = deviceId[2];
        bytes[6] = deviceId[3];
        bytes[7] = deviceId[4];
        bytes[8] = deviceId[5];
        bytes[9] = deviceId[6];

        this.safeguardSendData(bytes, 500, EnumAck.ACK_BIND_USER);
        //this.sendDataToDevice(bytes);

    }

    /**
     * 下发sha256校验第一包
     *
     * @param shaBytes
     */
    public void sendSha256PkgOne(byte[] shaBytes) {
        byte[] bytes = new byte[19];
        bytes[0] = (byte) 0xdb;
        bytes[1] = (byte) 0x10;
        bytes[2] = (byte) 0x04;

        for (int i = 3, j = 0; i < bytes.length; i++, j++) {
            bytes[i] = shaBytes[j];
        }

        this.sendDataToDevice(bytes);
    }

    /**
     * 下发sha256校验第二包
     *
     * @param shaBytes
     */
    public void sendSha256PkgTwo(byte[] shaBytes) {
        byte[] bytes = new byte[19];
        bytes[0] = (byte) 0xdb;
        bytes[1] = (byte) 0x10;
        bytes[2] = (byte) 0x05;

        for (int i = 3, j = 0; i < bytes.length; i++, j++) {
            bytes[i] = shaBytes[j];
        }

        this.sendDataToDevice(bytes);
    }

    /**
     * 消息重发机制
     *
     * @param bytes
     * @param timeout
     * @param ack
     */
    private void safeguardSendData(byte[] bytes, int timeout, EnumAck ack) {
        if (repeatSendThread != null &&
                repeatSendThread.isAlive()) {
            repeatSendThread.setRunState(false);
        }
        expectAck = ack;
        repeatSendThread = new RepeatSendThread(bytes, timeout, ack);
        repeatSendThread.start();
    }

    /**
     * 重发保障机制处理
     * 1.次数：3次
     * 2.间隔时间
     *
     * @author fenghui
     */
    class RepeatSendThread extends Thread {
        private byte[] bytes;
        private int timeout = 1000;
        private EnumAck enumAck;
        public boolean isRunning = true;

        public RepeatSendThread(byte[] bs, int to, EnumAck ack) {
            this.bytes = bs;
            this.timeout = to;
            this.enumAck = ack;
        }

        public void setRunState(boolean state) {
            isRunning = state;
        }

        @Override
        public void run() {
            expectAck = null;
            int i = 0;
            while (isRunning && (i++ < 2)) {
                if (expectAck == enumAck) {
                    ULog.e("RepeatSendThread", "same expectAck, return thread." + "," + System.currentTimeMillis());
                    break;
                }
                ULog.e("RepeatSendThread", "send cmd thread. type is :" + enumAck + "," + System.currentTimeMillis());
                sendDataToDevice(bytes);
                try {
                    Thread.sleep(timeout);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 开始心跳
     */
    public void startConnHeartbeat() {
        if (mHandler == null) {
            HandlerThread handlerThread = new HandlerThread("WeightDataHandle");
            handlerThread.start();
            mHandler = new Handler(handlerThread.getLooper());
        }
        mHandler.removeCallbacks(heartbeatRunnable);

        mHandler.post(heartbeatRunnable);
    }

    /**
     * 停止心跳
     */
    public void stopConnHeartbeat() {
        if (mHandler != null) {
            mHandler.removeCallbacks(heartbeatRunnable);
        }
    }

    /**
     * 心跳线程
     */
    Runnable heartbeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendDataTime > sendDataTimeout) {
                sendHeartBeatCmd();
            }
            mHandler.postDelayed(this, 300);
        }
    };


    /**
     * 释放资源的方法
     */
    public void release() {
        if (mHandler != null) {
            mHandler.removeCallbacks(heartbeatRunnable);
        }
        //停止线程
        repeatSendThread.isRunning = false;


    }
}